/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package evotingclient.model;

import evotingclient.utilis.SplitMessage;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.security.cert.Certificate;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.DatatypeConverter;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.ssl.SslFilter;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import sun.security.pkcs.PKCS10;

/**
 *
 * @author Pawel
 */
public class PKWClientHandler extends IoHandlerAdapter {
    
   

    private Model model;

    public PKWClientHandler(Model model) {
        this.model = model;
    }

   
    private String bytesToString(byte[] bytes){
        return DatatypeConverter.printBase64Binary(bytes);
    }
    
    private byte[] stringToBytes(String string){
        return DatatypeConverter.parseBase64Binary(string);
    }
    
    
    @Override
    public void sessionOpened(IoSession session) throws Exception {
        // Hello message
            System.out.println("Będę wysyłał wiadomość");
            Element ss = new Element("session");
            ss.setAttribute("name", "registration");
            Element msg = new Element("msg");
            Document doc = new Document(ss);
        
            PersonalData pd = model.getPersonalData();
            msg.addContent(MyXmlParser.parseToXmlSimpleObject(pd));
            
           
            byte[] pkcs10 = model.getSingRequst();
            Element singrec = new Element("PKCS10");
            singrec.addContent(bytesToString(pkcs10));
            
            msg.addContent(singrec);
            ss.addContent(msg);
 
            
            XMLOutputter out = new XMLOutputter();
            out.setFormat(Format.getPrettyFormat());
            
            /*String str = out.outputString(doc);
            IoBuffer buf = IoBuffer.allocate(str.length()+5);
            buf.putString(str, null);*/
            
            session.write(out.outputString(doc));
            System.out.println("Wysłałem");
            //session.write("whatever");
    }
    
    @Override
    public void messageReceived(IoSession session, Object message) throws CharacterCodingException {
        String s = ((IoBuffer) message).getString(Charset.forName("UTF-8").newDecoder());
        System.out.println(s);
        parseMessage(session, s);
    }

    private void parseMessage(IoSession session, Object message) {
         SAXBuilder builder = new SAXBuilder();
         try {
            Document document = builder.build(new StringReader(message.toString()));
            Element root = document.getRootElement();
            if(root.getName().equals("session")) {
                String sessionName = root.getAttribute("name").getValue();
                Element msg = root.getChild("msg");
                Document response = null;
                if(sessionName.equalsIgnoreCase("registration")) {
                    response = handleRegistration(msg);
                } else if(sessionName.equalsIgnoreCase("cardgen")) {
                    response = handleCardGeneration(msg);
                }else {
                    throw new JDOMException("Wrong session name");
                }
                
                
            } else {
                throw new JDOMException("No session given");
            }
        } catch(JDOMException e) {
            System.out.println("Malformed XML");
            System.out.println(e.getMessage());
        } catch(Exception e) { e.printStackTrace(); }
         
         session.close(true);
        
    }
    
    boolean importCertificate(Element certificate) throws IOException, InterruptedException{
        SplitMessage sm = new SplitMessage();
        String message = sm.combineMessage(certificate);
        System.out.println(message);
        model.saveCertificate(stringToBytes(message));
        int ret = model.importSignedCertificate();
        return ret == 0;
    }
    
     private Document handleRegistration(Element msg) {
            Element certificate = msg.getChild("signedCertificate");
            String result = certificate.getChildText("result");
            if(result.equals("OK")){
                System.out.println("Udało się podpisać certificate");
            try {
                boolean imported = importCertificate(certificate.getChild("certificate"));
                if(imported)
                    model.signal("Certificate signed successfully");
                else{
                    model.signal("Failed to import signed certificate");
                }
            } catch (IOException ex) {
                Logger.getLogger(PKWClientHandler.class.getName()).log(Level.SEVERE, null, ex);
                model.signal("Failed to import signed certificate : " + ex.getMessage() );
            } catch (InterruptedException ex) {
                Logger.getLogger(PKWClientHandler.class.getName()).log(Level.SEVERE, null, ex);
                model.signal("Failed to import signed certificate : " + ex.getMessage() );
            }
            }
            return null;
            
    }

    private Document handleCardGeneration(Element msg) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
